package com.rongke.web.lianpay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lianpay.api.util.TraderRSAUtil;
import com.rongke.model.*;
import com.rongke.service.*;
import com.rongke.sms.SmsService;
import com.rongke.sms.SmsTempletEnum;
import com.rongke.utils.DateUtils;
import com.rongke.web.lianpay.bean.BankCardPayBean;
import com.rongke.web.lianpay.bean.BusinessNoticeBean;
import com.rongke.web.lianpay.bean.NotifyResponseBean;
import com.rongke.web.lianpay.constant.PaymentConstant;
import com.rongke.web.lianpay.constant.PaymentStatusEnum;
import com.rongke.web.lianpay.util.SignUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;

/**
 * 这个Controller需放到服务器上运行调试 异步回调接口 
 * 用于接收连连付款状态 只有生成连连支付单的订单才会有异步回调通知，
 * 没生成连连支付单的订单连连是不会提交到银行渠道走付款流程
 * 
 * 用spring mvc获取需要配置下面 或者参考另一个文件夹的异步回调demo从http request 数据流中获取
 * <mvc:annotation-driven> <mvc:message-converters register-defaults="false">
 * <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <bean id="fastJsonHttpMessageConverter"
 * class=
 * "org.springframework.http.converter.json.MappingJackson2HttpMessageConverter "
 * > <property name="supportedMediaTypes"> <list>
 * <value>text/html;charset=UTF-8</value>
 * <value>application/json;charset=UTF-8</value>
 * <value>text/json;charset=UTF-8</value> </list> </property> </bean>
 * </mvc:message-converters> </mvc:annotation-driven>
 * 
 * @author lihp
 * @date 2017-3-17 上午09:55:30
 */

@Controller
@RequestMapping(value="/api/lianpay")
public class ImmediatePayNotifyController {

	private static final Logger logger = LoggerFactory.getLogger(ImmediatePayNotifyController.class);
	@Autowired
	private UserService userService;
	@Autowired
	private LoanOrderService loanOrderService;
	@Autowired
	private PersonRecordService personRecordService;
	@Autowired
	private MsgModelService msgModelService;
	@Autowired
	private SmsService smsService;
	@Autowired
	private OrderExtendService orderExtendService;
	/**
	 * 实时支付平台异步通知更新
	 * 
	 * @param
	 * @return
	 */
	@RequestMapping(value = "/tradepayapi/receiveNotify",
			method = RequestMethod.POST)
	@ResponseBody
	public NotifyResponseBean receiveNotify(@RequestBody BusinessNoticeBean businessNoticeBean,Long orderId) throws ParseException {
		logger.info("notify request:" + businessNoticeBean.toString());
		NotifyResponseBean responseBean = new NotifyResponseBean();
		boolean signCheck = TraderRSAUtil.checksign(PaymentConstant.PUBLIC_KEY_ONLINE,
				SignUtil.genSignData(JSONObject.parseObject(JSONObject.toJSONString(businessNoticeBean))),
				businessNoticeBean.getSign());
		if (!signCheck) {
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.error("返回结果验签异常,可能数据被篡改");
			// 回调内容先验签，再处理相应逻辑
			responseBean.setRet_code("9999");
			responseBean.setRet_msg("未知异常");
		}
		LoanOrder loanOrder = loanOrderService.selectById(orderId);
		if (businessNoticeBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_SUCCESS.getValue())) {
			// TODO 商户更新订单为成功，处理自己的业务逻辑
			logger.info("商户更新订单为成功，处理自己的业务逻辑");
			if(loanOrder!=null&&loanOrder.getOrderStatus()!=3){
				loanOrder.setGiveStatus(2);
				loanOrder.setOrderStatus(3);
				loanOrder.setGiveTime(new Date());
				//改变时间
				loanOrder.setLimitPayTime(DateUtils.dayAdd(loanOrder.getLimitDays(), new Date()));
				loanOrder.setOverdueTime(DateUtils.dayAdd(loanOrder.getLimitDays()+loanOrder.getAllowDays(),new Date()));
				loanOrderService.updateById(loanOrder);
				//统计
				EntityWrapper<PersonRecord> ew = new EntityWrapper();
				PersonRecord personRecord = personRecordService.selectOne(ew);
				personRecord.setOutOrderCount(personRecord.getOutOrderCount()+1);
				personRecord.setOutMoney(personRecord.getOutMoney().add(loanOrder.getRealMoney()));
				personRecordService.updateById(personRecord);
				//发送打款成功短信
				EntityWrapper<MsgModel> ewMsg = new EntityWrapper();
				ewMsg.eq("type",1);
				MsgModel msgModel = msgModelService.selectOne(ewMsg);//找到短信模板
				//将信息部分替换
				User user = userService.selectById(loanOrder.getUserId());
				String bankNum=loanOrder.getBankCardNum().substring(loanOrder.getBankCardNum().length()-4,loanOrder.getBankCardNum().length());//银行卡后四位
				String content = msgModel.getContent().replaceAll("</?[^>]+>", "").replace("#userName",user.getUserName()).replace("#number",bankNum).replace("#gmtDateTime",DateUtils.YYMMDDDateChinese(loanOrder.getGmtDatetime())).replace("#money",loanOrder.getRealMoney().toString());
				logger.info("短信内容+++++++++++++++++++++++++++++"+content);
				SmsTempletEnum.REMINDSEND.setTypeName(content);
				smsService.smsCodeByType(user.getPhone(), 3);
				responseBean.setRet_code("0000");
				responseBean.setRet_msg("交易成功");
				logger.error("交易成功");
			}
		} else if (businessNoticeBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_FAILURE.getValue())) {
			// TODO 商户更新订单为失败，处理自己的业务逻辑
			if(loanOrder!=null){
				loanOrder.setGiveStatus(2);
				loanOrderService.updateById(loanOrder);
			}
		} else {
			// TODO 返回订单为退款状态 ，商户可以更新订单为失败或者退款
			// 退款这种情况是极小概率情况下才会发生的，个别银行处理机制是先扣款后再打款给用户时，
			// 才检验卡号姓名信息的有效性，当卡号姓名信息有误发生退款，实际上钱没打款到商户。
			// 这种情况商户代码上也可不做考虑，如发生用户投诉未收到钱，可直接联系连连客服，连连会跟银行核对
			// 退款情况，异步通知会通知两次，先通知成功，后通知退款（极小概率情况下才会发生的）
			if(loanOrder!=null){
				loanOrder.setGiveStatus(2);
				loanOrderService.updateById(loanOrder);
			}
		}
		//回调内容先验签，再处理相应逻辑*/

		return responseBean;
	}

	/**
	 * 分期支付平台异步通知更新
	 *
	 * @param
	 * @return
	 */
	@RequestMapping(value = "/fenqipayapi/receiveNotify",
			method = RequestMethod.POST)
	@ResponseBody
	public NotifyResponseBean receiveNotif(@RequestBody BankCardPayBean bankCardPayBean,String orderId,String money,String no_order) throws ParseException {
		logger.info("notify request:" + bankCardPayBean.toString());
		NotifyResponseBean responseBean = new NotifyResponseBean();
		boolean signCheck = TraderRSAUtil.checksign(PaymentConstant.PUBLIC_KEY_ONLINE,
				SignUtil.genSignData(JSONObject.parseObject(JSONObject.toJSONString(bankCardPayBean))),
				bankCardPayBean.getSign());
		if (!signCheck) {
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.error("返回结果验签异常,可能数据被篡改");
			// 回调内容先验签，再处理相应逻辑
			responseBean.setRet_code("9999");
			responseBean.setRet_msg("未知异常");
		}
		LoanOrder loanOrder = loanOrderService.selectById(orderId);
		User user = userService.selectById(loanOrder.getUserId());
		if (bankCardPayBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_SUCCESS.getValue())) {
			// TODO 商户更新订单为成功，处理自己的业务逻辑
			logger.info("商户更新订单为成功，处理自己的业务逻辑");
			if(loanOrder!=null&&loanOrder.getOrderStatus()!=6){
				loanOrder.setOrderStatus(6);
				try {
					if(DateUtils.YYMMDDDate(new Date()).getTime()>loanOrder.getOverdueTime().getTime()){
                        loanOrder.setPayStatus(2);//超出容限期还款
                        user.setMoney(user.getMoney().add(loanOrder.getBorrowMoney()));
                    }else{
                        loanOrder.setPayStatus(1);//正常还款
                        user.setMoney(user.getMoney().add(loanOrder.getBorrowMoney()));
                    }
				} catch (ParseException e) {
					e.printStackTrace();
				}
				loanOrder.setRealPayMoney(new BigDecimal(money));
				loanOrder.setRealPayTime(new Date());
				loanOrder.setLianRepayNum(no_order);
				loanOrderService.updateById(loanOrder);

				user.setIsPay(0);
				user.setIsOld(1);
				userService.updateById(user);

				//统计
				EntityWrapper<PersonRecord> ew = new EntityWrapper();
				PersonRecord personRecord = personRecordService.selectOne(ew);
				personRecord.setOverOrderCount(personRecord.getOverOrderCount()+1);
				personRecordService.updateById(personRecord);

				//发送打款成功短信
				EntityWrapper<MsgModel> ewMsg = new EntityWrapper();
				ewMsg.eq("type",4);
				MsgModel msgModel = msgModelService.selectOne(ewMsg);//找到短信模板
				//将信息部分替换
				String content = msgModel.getContent().replaceAll("</?[^>]+>", "").replace("#userName",user.getUserName()).replace("#gmtDateTime",DateUtils.YYMMDDDateChinese(loanOrder.getGmtDatetime()));
				SmsTempletEnum.REMINDSEND.setTypeName(content);
				logger.info("短信内容+++++++++++++++++++++++++++++"+content);
				smsService.smsCodeByType(user.getPhone(), 3);
				responseBean.setRet_code("0000");
				responseBean.setRet_msg("交易成功");
				logger.error("交易成功");
			}
		} else if (bankCardPayBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_FAILURE.getValue())) {
			// TODO 商户更新订单为失败，处理自己的业务逻辑
		} else {
			// TODO 返回订单为退款状态 ，商户可以更新订单为失败或者退款
			// 退款这种情况是极小概率情况下才会发生的，个别银行处理机制是先扣款后再打款给用户时，
			// 才检验卡号姓名信息的有效性，当卡号姓名信息有误发生退款，实际上钱没打款到商户。
			// 这种情况商户代码上也可不做考虑，如发生用户投诉未收到钱，可直接联系连连客服，连连会跟银行核对
			// 退款情况，异步通知会通知两次，先通知成功，后通知退款（极小概率情况下才会发生的）
		}
		//回调内容先验签，再处理相应逻辑*/

		return responseBean;
	}

	/**
	 * 分期支付平台异步通知更新2(自动扣款)
	 *
	 * @param
	 * @return
	 */
	@RequestMapping(value = "/fenqipayapi2/receiveNotify",
			method = RequestMethod.POST)
	@ResponseBody
	public NotifyResponseBean receiveNotif(@RequestBody BankCardPayBean bankCardPayBean,String orderId) throws ParseException {
		logger.info("notify request:" + bankCardPayBean.toString());
		NotifyResponseBean responseBean = new NotifyResponseBean();
		boolean signCheck = TraderRSAUtil.checksign(PaymentConstant.PUBLIC_KEY_ONLINE,
				SignUtil.genSignData(JSONObject.parseObject(JSONObject.toJSONString(bankCardPayBean))),
				bankCardPayBean.getSign());
		if (!signCheck) {
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.error("返回结果验签异常,可能数据被篡改");
			// 回调内容先验签，再处理相应逻辑
			responseBean.setRet_code("9999");
			responseBean.setRet_msg("未知异常");
		}
		LoanOrder loanOrder = loanOrderService.selectById(orderId);
		User user = userService.selectById(loanOrder.getUserId());
		if (bankCardPayBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_SUCCESS.getValue())) {
			// TODO 商户更新订单为成功，处理自己的业务逻辑
			logger.info("商户更新订单为成功，处理自己的业务逻辑");
			if(loanOrder!=null&&loanOrder.getOrderStatus()!=6){
				loanOrder.setOrderStatus(6);
				try {
					if(DateUtils.YYMMDDDate(new Date()).getTime()>loanOrder.getOverdueTime().getTime()){
						loanOrder.setPayStatus(2);//超出容限期还款
						user.setMoney(user.getMoney().add(loanOrder.getBorrowMoney()));
					}else{
						loanOrder.setPayStatus(1);//正常还款
						user.setMoney(user.getMoney().add(loanOrder.getBorrowMoney()));
					}
				} catch (ParseException e) {
					e.printStackTrace();
				}
				loanOrder.setRealPayMoney(new BigDecimal(bankCardPayBean.getMoney_order()));
				loanOrder.setRealPayTime(new Date());
				loanOrder.setLianRepayNum(bankCardPayBean.getNo_order());
				loanOrderService.updateById(loanOrder);

				user.setIsPay(0);
				user.setIsOld(1);
				userService.updateById(user);

				//统计
				EntityWrapper<PersonRecord> ew = new EntityWrapper();
				PersonRecord personRecord = personRecordService.selectOne(ew);
				personRecord.setOverOrderCount(personRecord.getOverOrderCount()+1);
				personRecordService.updateById(personRecord);

				logger.info("发送短信开始++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
				//发送打款成功短信
				EntityWrapper<MsgModel> ewMsg = new EntityWrapper();
				ewMsg.eq("type",4);
				MsgModel msgModel = msgModelService.selectOne(ewMsg);//找到短信模板
				//将信息部分替换
				String content = msgModel.getContent().replaceAll("</?[^>]+>", "").replace("#userName",user.getUserName()).replace("#gmtDateTime",DateUtils.YYMMDDDateChinese(loanOrder.getGmtDatetime()));
				logger.info("短信内容++++++++++++++++++++++++++++++++++++++++++++++++++++++++"+content);
				SmsTempletEnum.REMINDSEND.setTypeName(content);
				smsService.smsCodeByType(user.getPhone(), 3);
				responseBean.setRet_code("0000");
				responseBean.setRet_msg("交易成功");
				logger.error("交易成功");
			}
		} else if (bankCardPayBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_FAILURE.getValue())) {
			// TODO 商户更新订单为失败，处理自己的业务逻辑
		} else {
			// TODO 返回订单为退款状态 ，商户可以更新订单为失败或者退款
			// 退款这种情况是极小概率情况下才会发生的，个别银行处理机制是先扣款后再打款给用户时，
			// 才检验卡号姓名信息的有效性，当卡号姓名信息有误发生退款，实际上钱没打款到商户。
			// 这种情况商户代码上也可不做考虑，如发生用户投诉未收到钱，可直接联系连连客服，连连会跟银行核对
			// 退款情况，异步通知会通知两次，先通知成功，后通知退款（极小概率情况下才会发生的）
		}
		//回调内容先验签，再处理相应逻辑*/

		return responseBean;
	}

	/**
	 * 分期支付平台异步通知更新3(续期)
	 *
	 * @param
	 * @return
	 */
	@RequestMapping(value = "/fenqipayapi3/receiveNotify",
			method = RequestMethod.POST)
	@ResponseBody
	public NotifyResponseBean receiveNotif3(@RequestBody BankCardPayBean bankCardPayBean,String orderId,String money,String extendId) throws ParseException {
		logger.info("续期回调开始");
		logger.info("notify request:" + bankCardPayBean.toString());
		NotifyResponseBean responseBean = new NotifyResponseBean();
		boolean signCheck = TraderRSAUtil.checksign(PaymentConstant.PUBLIC_KEY_ONLINE,
				SignUtil.genSignData(JSONObject.parseObject(JSONObject.toJSONString(bankCardPayBean))),
				bankCardPayBean.getSign());
		if (!signCheck) {
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.error("返回结果验签异常,可能数据被篡改");
			// 回调内容先验签，再处理相应逻辑
			responseBean.setRet_code("9999");
			responseBean.setRet_msg("未知异常");
		}
		LoanOrder loanOrder = loanOrderService.selectById(orderId);
		User user = userService.selectById(loanOrder.getUserId());
		OrderExtend orderExtend = orderExtendService.selectById(extendId);
		if (bankCardPayBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_SUCCESS.getValue())) {
			// TODO 商户更新订单为成功，处理自己的业务逻辑
			logger.info("商户更新订单为成功，处理自己的业务逻辑");
			if(orderExtend.getStatus()!=1){
				loanOrder.setOrderStatus(3);
				loanOrder.setRealPayMoney(loanOrder.getRealPayMoney().add(new BigDecimal(money)));
				loanOrder.setNeedPayMoney(loanOrder.getNeedPayMoney().subtract(loanOrder.getOverdueMoney()));
				loanOrder.setWateMoney(loanOrder.getWateMoney().subtract(loanOrder.getOverdueMoney()));
				//时间
				loanOrder.setLimitPayTime(DateUtils.dayAdd(orderExtend.getExtendDays()-1+loanOrder.getOverdueDays(),loanOrder.getLimitPayTime()));
				loanOrder.setOverdueTime(DateUtils.dayAdd(orderExtend.getExtendDays()-1+loanOrder.getOverdueDays(),loanOrder.getOverdueTime()));
				//清除逾期的金额天数
				loanOrder.setOverdueDays(0);
				loanOrder.setOverdueMoney(new BigDecimal(0));
				loanOrder.setAllowDays(0);
				loanOrder.setAllowMoney(new BigDecimal(0));
				loanOrderService.updateById(loanOrder);

				orderExtend.setStatus(1);
				orderExtendService.updateById(orderExtend);

				//发送续期成功短信
				EntityWrapper<MsgModel> ewMsg = new EntityWrapper();
				ewMsg.eq("type",6);
				MsgModel msgModel = msgModelService.selectOne(ewMsg);//找到短信模板
				//将信息部分替换
				String content = msgModel.getContent().replaceAll("</?[^>]+>", "").replace("limitPayTime",DateUtils.YYMMDDDateChinese(loanOrder.getLimitPayTime())).replace("userName",user.getUserName());
				SmsTempletEnum.REMINDSEND.setTypeName(content);
				logger.info("短信内容+++++++++++++++++++++++++++++"+content);
				smsService.smsCodeByType(user.getPhone(), 3);
				responseBean.setRet_code("0000");
				responseBean.setRet_msg("交易成功");
				logger.error("交易成功");
			}
		} else if (bankCardPayBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_FAILURE.getValue())) {
			// TODO 商户更新订单为失败，处理自己的业务逻辑
		} else {
			// TODO 返回订单为退款状态 ，商户可以更新订单为失败或者退款
			// 退款这种情况是极小概率情况下才会发生的，个别银行处理机制是先扣款后再打款给用户时，
			// 才检验卡号姓名信息的有效性，当卡号姓名信息有误发生退款，实际上钱没打款到商户。
			// 这种情况商户代码上也可不做考虑，如发生用户投诉未收到钱，可直接联系连连客服，连连会跟银行核对
			// 退款情况，异步通知会通知两次，先通知成功，后通知退款（极小概率情况下才会发生的）
		}
		//回调内容先验签，再处理相应逻辑*/

		return responseBean;
	}
	/**
	 * 分期支付平台异步通知更新
	 *
	 * @param
	 * @return
	 */
	@RequestMapping(value = "/sign",
			method = RequestMethod.POST)
	@ResponseBody
	public String sign(@RequestBody BankCardPayBean bankCardPayBean) {
		// 用商户自己的私钥加签
		String sign = SignUtil.genRSASign(JSON.parseObject(JSON.toJSONString(bankCardPayBean)));
		return sign;
	}

}
